﻿#define _CRT_SECURE_NO_WARNINGS 1

#include"matrix.h"

//int mapToCompressedIndex(int i, int j, MatrixType type)
//{
//    switch (type) {
//    case MATRIX_SYMMETRIC:
//        if (i >= j) return i * (i + 1) / 2 + j;
//        else return j * (j + 1) / 2 + i;
//
//    case MATRIX_LOWER_TRI:
//        if (i >= j) return i * (i + 1) / 2 + j;
//        return -1;
//
//    case MATRIX_UPPER_TRI:
//        if (i <= j) return j * (j + 1) / 2 + i;
//        return -1;
//
//    case MATRIX_DIAGONAL:
//        if (i == j) return i;
//        return -1;
//
//    case MATRIX_TRIDIAGONAL:
//        if (abs(i - j) <= 1)
//        {
//            // 三对角矩阵映射：按行存储所有三对角元素
//            if (i == 0 && j == 0) return 0;           // a₀
//            if (i == 0 && j == 1) return 1;           // b₀
//            return 3 * i - 1 + (j - i + 1);          // 通用公式
//        }
//        return -1;
//
//    default:
//        return -1;
//    }
//}
//int mapToCompressedIndex(int i, int j, MatrixType type) 
//{
//    switch (type) {
//    case MATRIX_SYMMETRIC:
//        return (i >= j) ? i * (i + 1) / 2 + j : j * (j + 1) / 2 + i;
//
//    case MATRIX_LOWER_TRI:
//        return (i >= j) ? i * (i + 1) / 2 + j : -1;
//
//    case MATRIX_UPPER_TRI://按列优先
//        return (i <= j) ? j * (j + 1) / 2 + i : -1;
//
//    case MATRIX_DIAGONAL:
//        return (i == j) ? i : -1;
//
//    case MATRIX_TRIDIAGONAL:
//        if (abs(i - j) <= 1) {
//            // 三对角矩阵映射：按行存储所有三对角元素
//            if (i == 0 && j == 0) return 0;           // a₀
//            if (i == 0 && j == 1) return 1;           // b₀
//            return 3 * i - 1 + (j - i + 1);          // 通用公式
//        }
//        return -1;
//
//    default:
//        return -1;
//    }
//}

int mapToCompressedIndex(int i, int j,int n, MatrixType type)
{
    switch (type) {
    case MATRIX_SYMMETRIC:
        return (i >= j) ? i * (i + 1) / 2 + j : j * (j + 1) / 2 + i;

    case MATRIX_LOWER_TRI:
        return (i >= j) ? i * (i + 1) / 2 + j : -1;

    case MATRIX_UPPER_TRI:
        return (i <= j) ? i*n-i*(i-1)/2+(j-i) : -1;

    case MATRIX_DIAGONAL:
        return (i == j) ? i : -1;

    case MATRIX_TRIDIAGONAL:
        if (abs(i - j) <= 1) {
            // 三对角矩阵映射：按行存储所有三对角元素
            if (i == 0 && j == 0) return 0;           // a₀
            if (i == 0 && j == 1) return 1;           // b₀
            return 3 * i - 1 + (j - i + 1);          // 通用公式
        }
        return -1;

    default:
        return -1;
    }
}
CompressedMatrix* compressMatrix(int** matrix, int n, MatrixType type, int constant)
{
    CompressedMatrix* cm = (CompressedMatrix*)malloc(sizeof(CompressedMatrix));
    cm->n = n;
    cm->type = type;
    cm->constant = constant;

    // 计算压缩后的大小
    switch (type) {
    case MATRIX_SYMMETRIC:
    case MATRIX_LOWER_TRI:
    case MATRIX_UPPER_TRI:
        cm->size = n * (n + 1) / 2;
        break;
    case MATRIX_DIAGONAL:
        cm->size = n;
        break;
    case MATRIX_TRIDIAGONAL:
        cm->size = 3 * n - 2;
        break;
    default:
        cm->size = 0;
    }

    cm->data = (int*)malloc(cm->size * sizeof(int));

    //压缩操作
    int idx = 0;
    for (int i = 0; i < n; i++) 
    {
        for (int j = 0; j < n; j++) 
        {
            int compressed_idx = mapToCompressedIndex(i, j,n, type);
            if (compressed_idx >= 0 && compressed_idx < cm->size)
            {
                cm->data[compressed_idx] = matrix[i][j];
            }
        }
    }
    return cm;
    
}


// 显示压缩数组的地址和值
void displayCompressed(CompressedMatrix* cm) {
    for (int i = 0; i < cm->size; i++) {
        printf("%d: %d\n", i, cm->data[i]);
    }
}

int getValueFromCompressed(CompressedMatrix* cm, int i, int j)
{
    if (i < 0 || i >= cm->n || j < 0 || j >= cm->n)
    {
        printf("索引越界: i=%d, j=%d (矩阵维度: %d×%d)\n", i, j, cm->n);
        return -1;
    }

    int compressed_idx = mapToCompressedIndex(i, j,  cm->n,cm->type);

    if (compressed_idx == -1)
    {
        // 返回常数区域的值
        switch (cm->type) {
        case MATRIX_LOWER_TRI:
            if (i < j) return cm->constant;
            break;
        case MATRIX_UPPER_TRI:
            if (i > j) return cm->constant;
            break;
        case MATRIX_DIAGONAL:
            if (i != j) return 0;
            break;
        case MATRIX_TRIDIAGONAL:
            if (abs(i - j) > 1) return 0;
            break;
        default:
            return 0;
        }
        return cm->constant;
    }
    if (compressed_idx >= 0 && compressed_idx < cm->size) 
    {
        return cm->data[compressed_idx];
    }
    else 
    {
        printf("压缩索引越界: idx=%d (最大允许: %d)\n", compressed_idx, cm->size - 1);
        return -1;
    }
}


// 显示原始矩阵
void displayOriginalMatrix(int** matrix, int n) 
{
    printf("原始矩阵 %d×%d:\n", n, n);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            printf("%2d ", matrix[i][j]);
        }
        printf("\n");
    }
}


int** createSymmetricMatrix(int n)
{
    int** matrix = (int**)malloc(n * sizeof(int*));
    for (int i = 0; i < n; i++) 
    {
        matrix[i] = (int*)malloc(n * sizeof(int));
        for (int j = 0; j < n; j++)
        {
            if (i <= j) 
            {
                matrix[i][j] = i * n + j + 1;
            }
            else 
            {
                matrix[i][j] = matrix[j][i]; // 保持对称性
            }
        }
    }
    return matrix;
}

int** createLowerTriangularMatrix(int n) 
{
    int** matrix = (int**)malloc(n * sizeof(int*));
    for (int i = 0; i < n; i++) {
        matrix[i] = (int*)malloc(n * sizeof(int));
        for (int j = 0; j < n; j++) {
            if (i >= j) {
                matrix[i][j] = i * n + j + 1; // 下三角区域有值
            }
            else {
                matrix[i][j] = 0; // 上三角区域为0
            }
        }
    }
    return matrix;
}

int** createUpperTriangularMatrix(int n)
{
    int** matrix = (int**)malloc(n * sizeof(int*));
    for (int i = 0; i < n; i++) {
        matrix[i] = (int*)malloc(n * sizeof(int));
        for (int j = 0; j < n; j++) {
            if (i <= j) {
                matrix[i][j] = i * n + j + 1; // 上三角区域有值
            }
            else {
                matrix[i][j] = 0; // 下三角区域为0
            }
        }
    }
    return matrix;
}


int** createDiagonalMatrix(int n)
{
    int** matrix = (int**)malloc(n * sizeof(int*));
    for (int i = 0; i < n; i++) {
        matrix[i] = (int*)malloc(n * sizeof(int));
        for (int j = 0; j < n; j++) {
            if (i == j) {
                matrix[i][j] = i + 1; // 对角线有值
            }
            else {
                matrix[i][j] = 0; // 非对角线为0
            }
        }
    }
    return matrix;
}

int** createTriDiagonalMatrix(int n)
{
    int** matrix = (int**)malloc(n * sizeof(int*));
    for (int i = 0; i < n; i++) {
        matrix[i] = (int*)malloc(n * sizeof(int));
        for (int j = 0; j < n; j++) {
            int diff = abs(i - j);
            if (diff == 0) {
                matrix[i][j] = (i + 1) * 10; // 主对角线
            }
            else if (diff == 1) {
                matrix[i][j] = (i + 1) * 10 + (j + 1); // 次对角线
            }
            else {
                matrix[i][j] = 0; // 其他区域为0
            }
        }
    }
    return matrix;
}


void freeMatrix(int** matrix, int n)
{
    for (int i = 0; i < n; i++)
    {
        free(matrix[i]);
    }
    free(matrix);
}

void freeCompressedMatrix(CompressedMatrix* cm)
{
    free(cm->data);
    free(cm);
}


int** readMatrixFromFile(const char* filename, int* n)
{
    FILE* file = fopen(filename, "r");
    if (file == NULL) 
    {
        printf("错误: 无法打开文件 %s\n", filename);
        return NULL;
    }

    // 读取矩阵维度
    if (fscanf(file, "%d", n) != 1) 
    {
        printf("错误: 读取矩阵维度失败\n");
        fclose(file);
        return NULL;
    }

    // 分配内存
    int** matrix = (int**)malloc(*n * sizeof(int*));
    for (int i = 0; i < *n; i++)
    {
        matrix[i] = (int*)malloc(*n * sizeof(int));
        for (int j = 0; j < *n; j++) 
        {
            if (fscanf(file, "%d", &matrix[i][j]) != 1) 
            {
                printf("错误: 读取矩阵数据失败\n");
                fclose(file);
                // 清理已分配的内存
                for (int k = 0; k <= i; k++)
                {
                    free(matrix[k]);
                }
                free(matrix);
                return NULL;
            }
        }
    }

    fclose(file);
    printf("成功从文件 %s 读取 %dx%d 矩阵\n", filename, *n, *n);
    return matrix;
}


void saveCompressedMatrixToFile(CompressedMatrix* cm, const char* filename)
{
    FILE* file = fopen(filename, "w");
    if (file == NULL) 
    {
        printf("错误: 无法创建文件 %s\n", filename);
        return;
    }
    // 写入元数据
    fprintf(file, "%d\n", cm->n);  // 矩阵维度
    fprintf(file, "%s\n", getMatrixTypeName(cm->type));  // 矩阵类型
    fprintf(file, "%d\n", cm->constant);  // 常数区域值
    fprintf(file, "%d\n", cm->size);  // 压缩数据大小

    // 写入压缩数据
    for (int i = 0; i < cm->size; i++) {
        fprintf(file, "%d ", cm->data[i]);
        if ((i + 1) % 10 == 0) fprintf(file, "\n"); // 每10个数据换行
    }
    fprintf(file, "\n");

    fclose(file);
    printf("压缩矩阵已保存到文件: %s\n", filename);

}

CompressedMatrix* loadCompressedMatrixFromFile(const char* filename)
{
    FILE* file = fopen(filename, "r");
    if (file == NULL) {
        printf("错误: 无法打开文件 %s\n", filename);
        return NULL;
    }

    CompressedMatrix* cm = (CompressedMatrix*)malloc(sizeof(CompressedMatrix));

    // 读取元数据
    char typeName[50];
    if (fscanf(file, "%d", &cm->n) != 1 ||
        fscanf(file, "%s", typeName) != 1 ||
        fscanf(file, "%d", &cm->constant) != 1 ||
        fscanf(file, "%d", &cm->size) != 1) {
        printf("错误: 读取元数据失败\n");
        fclose(file);
        free(cm);
        return NULL;
    }

    cm->type = getMatrixTypeFromName(typeName);
    cm->data = (int*)malloc(cm->size * sizeof(int));
    // 读取压缩数据
    for (int i = 0; i < cm->size; i++) {
        if (fscanf(file, "%d", &cm->data[i]) != 1) {
            printf("错误: 读取压缩数据失败\n");
            fclose(file);
            free(cm->data);
            free(cm);
            return NULL;
        }
    }

    fclose(file);
    printf("成功从文件 %s 加载压缩矩阵\n", filename);
    return cm;
}

MatrixType getMatrixTypeFromName(const char* name)
{
    if (strcmp(name, "symmetric") == 0) return MATRIX_SYMMETRIC;
    if (strcmp(name, "lower_triangular") == 0) return MATRIX_LOWER_TRI;
    if (strcmp(name, "upper_triangular") == 0) return MATRIX_UPPER_TRI;
    if (strcmp(name, "diagonal") == 0) return MATRIX_DIAGONAL;
    if (strcmp(name, "tridiagonal") == 0) return MATRIX_TRIDIAGONAL;
}

void saveMatrixToFile(int** matrix, int n, const char* filename)
{
    FILE* file = fopen(filename, "w");
    if (file == NULL) {
        printf("错误: 无法创建文件 %s\n", filename);
        return;
    }

    fprintf(file, "%d\n", n);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            fprintf(file, "%d ", matrix[i][j]);
        }
        fprintf(file, "\n");
    }

    fclose(file);
    printf("矩阵已保存到文件: %s\n", filename);
}


const char* getMatrixTypeName(MatrixType type) {
    switch (type) {
    case MATRIX_SYMMETRIC: return "symmetric";
    case MATRIX_LOWER_TRI: return "lower_triangular";
    case MATRIX_UPPER_TRI: return "upper_triangular";
    case MATRIX_DIAGONAL: return "diagonal";
    case MATRIX_TRIDIAGONAL: return "tridiagonal";
    default: return "unknown";
    }
}

//void createTestMatrixFile()
//{
//    // 1. 对称矩阵测试文件
//    FILE* file = fopen("symmetric_matrix.txt", "w");
//    fprintf(file, "3\n");
//    fprintf(file, "1 2 3\n");
//    fprintf(file, "2 4 5\n");
//    fprintf(file, "3 5 6\n");
//    fclose(file);
//    printf("创建: symmetric_matrix.txt (3x3对称矩阵)\n");
//
//    // 2. 下三角矩阵测试文件
//    file = fopen("lower_tri_matrix.txt", "w");
//    fprintf(file, "4\n");
//    fprintf(file, "1 0 0 0\n");
//    fprintf(file, "5 6 0 0\n");
//    fprintf(file, "9 10 11 0\n");
//    fprintf(file, "13 14 15 16\n");
//    fclose(file);
//    printf("创建: lower_tri_matrix.txt (4x4下三角矩阵)\n");
//
//    // 3. 上三角矩阵测试文件
//    file = fopen("upper_tri_matrix.txt", "w");
//    fprintf(file, "4\n");
//    fprintf(file, "1 2 3 4\n");
//    fprintf(file, "0 5 6 7\n");
//    fprintf(file, "0 0 8 9\n");
//    fprintf(file, "0 0 0 10\n");
//    fclose(file);
//    printf("创建: upper_tri_matrix.txt (4x4上三角矩阵)\n");
//
//    // 4. 对角矩阵测试文件
//    file = fopen("diagonal_matrix.txt", "w");
//    fprintf(file, "5\n");
//    fprintf(file, "1 0 0 0 0\n");
//    fprintf(file, "0 2 0 0 0\n");
//    fprintf(file, "0 0 3 0 0\n");
//    fprintf(file, "0 0 0 4 0\n");
//    fprintf(file, "0 0 0 0 5\n");
//    fclose(file);
//    printf("创建: diagonal_matrix.txt (5x5对角矩阵)\n");
//
//    // 5. 三对角矩阵测试文件
//    file = fopen("tridiagonal_matrix.txt", "w");
//    fprintf(file, "5\n");
//    fprintf(file, "2 1 0 0 0\n");
//    fprintf(file, "3 4 2 0 0\n");
//    fprintf(file, "0 5 6 3 0\n");
//    fprintf(file, "0 0 7 8 4\n");
//    fprintf(file, "0 0 0 9 10\n");
//    fclose(file);
//    printf("创建: tridiagonal_matrix.txt (5x5三对角矩阵)\n");
//}



void createMatrixFile()
{
    int n = 0;
    printf("\n请选择你想要生成的矩阵维度:\n");
    scanf("%d", &n);
    printf("\n请选择矩阵类型:\n");
    printf("1. 对称矩阵 (Symmetric)\n");
    printf("2. 下三角矩阵 (Lower Triangular)\n");
    printf("3. 上三角矩阵 (Upper Triangular)\n");
    printf("4. 对角矩阵 (Diagonal)\n");
    printf("5. 三对角矩阵 (Tridiagonal)\n");
    printf("请选择 (1-5): ");

    int choice;
    scanf("%d", &choice);
    if (choice == 1)
    {
        int** symmetricmatrix = createSymmetricMatrix(n);
        saveMatrixToFile(symmetricmatrix, n, "symmetric_matrix.txt");
        printf("创建: symmetric_matrix.txt (%dx%d对称矩阵)\n", n, n);
    }
    else if (choice == 2)
    {
        int** lowermatrix = createLowerTriangularMatrix(n);
        saveMatrixToFile(lowermatrix, n, "lower_tri_matrix.txt");
        printf("创建: lower_tri_matrix.txt (%dx%d下三角矩阵)\n", n, n);
    }
    else if (choice == 3)
    {
        int** uppermatrix = createUpperTriangularMatrix(n);
        saveMatrixToFile(uppermatrix, n, "upper_tri_matrix.txt");
        printf("创建: upper_tri_matrix.txt (%dx%d上三角矩阵)\n", n, n);

    }
    else if (choice == 4)
    {
        int** diagonalmatrix = createDiagonalMatrix(n);
        saveMatrixToFile(diagonalmatrix, n, "diagonal_matrix.txt");
        printf("创建: diagonal_matrix.txt (%dx%d对角矩阵)\n", n, n);

    }
    else if (choice == 5)
    {
        int** tridiagonalmatrix = createTriDiagonalMatrix(n);
        saveMatrixToFile(tridiagonalmatrix, n, "tridiagonal_matrix.txt");
        printf("创建: tridiagonal_matrix.txt (%dx%d三角矩阵)\n", n, n);
    }

}
